//
// 	NetFilterSDK
// 	Copyright (C) Vitaly Sidorov
//	All rights reserved.
//
//	This file is a part of the NetFilter SDK.
//	The code and information is provided "as-is" without
//	warranty of any kind, either expressed or implied.
//

#ifndef _LINKED_LIST

//
// Calculate the address of the base of the structure given its type, and an
// address of a field within the structure.
//
#ifndef CONTAINING_RECORD
#define CONTAINING_RECORD(address, type, field) \
    ((type *)((PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field)))
#endif

//
//  VOID
//  InitializeListHead(
//      PLIST_ENTRY ListHead
//      );
//

#define InitializeListHead(ListHead) ( \
    (ListHead)->Flink = (ListHead)->Blink = (ListHead))

//
//  BOOLEAN
//  IsListEmpty(
//      PLIST_ENTRY ListHead
//      );
//

#define IsListEmpty(ListHead) \
    ((ListHead)->Flink == (ListHead))

//
//  PLIST_ENTRY
//  RemoveHeadList(
//      PLIST_ENTRY ListHead
//      );
//

#define RemoveHeadList(ListHead)           \
    (ListHead)->Flink;                     \
    {                                      \
        RemoveEntryList((ListHead)->Flink) \
    }

//
//  PLIST_ENTRY
//  RemoveTailList(
//      PLIST_ENTRY ListHead
//      );
//

#define RemoveTailList(ListHead)           \
    (ListHead)->Blink;                     \
    {                                      \
        RemoveEntryList((ListHead)->Blink) \
    }

//
//  VOID
//  RemoveEntryList(
//      PLIST_ENTRY Entry
//      );
//

#define RemoveEntryList(Entry)        \
    {                                 \
        PLIST_ENTRY _EX_Blink;        \
        PLIST_ENTRY _EX_Flink;        \
        _EX_Flink = (Entry)->Flink;   \
        _EX_Blink = (Entry)->Blink;   \
        _EX_Blink->Flink = _EX_Flink; \
        _EX_Flink->Blink = _EX_Blink; \
    }

//
//  VOID
//  InsertTailList(
//      PLIST_ENTRY ListHead,
//      PLIST_ENTRY Entry
//      );
//

#define InsertTailList(ListHead, Entry)  \
    {                                    \
        PLIST_ENTRY _EX_Blink;           \
        PLIST_ENTRY _EX_ListHead;        \
        _EX_ListHead = (ListHead);       \
        _EX_Blink = _EX_ListHead->Blink; \
        (Entry)->Flink = _EX_ListHead;   \
        (Entry)->Blink = _EX_Blink;      \
        _EX_Blink->Flink = (Entry);      \
        _EX_ListHead->Blink = (Entry);   \
    }

//
//  VOID
//  InsertHeadList(
//      PLIST_ENTRY ListHead,
//      PLIST_ENTRY Entry
//      );
//

#define InsertHeadList(ListHead, Entry)  \
    {                                    \
        PLIST_ENTRY _EX_Flink;           \
        PLIST_ENTRY _EX_ListHead;        \
        _EX_ListHead = (ListHead);       \
        _EX_Flink = _EX_ListHead->Flink; \
        (Entry)->Flink = _EX_Flink;      \
        (Entry)->Blink = _EX_ListHead;   \
        _EX_Flink->Blink = (Entry);      \
        _EX_ListHead->Flink = (Entry);   \
    }

#endif //_LINKED_LIST
